package com.sc.nft.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.UserCouponsDao;
import com.sc.nft.entity.ActivityCoupons;
import com.sc.nft.entity.UserCoupons;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.dto.ActivityCouponsProductDTO;
import com.sc.nft.entity.dto.UseUserCouponsDTO;
import com.sc.nft.entity.dto.UserCouponsDTO;
import com.sc.nft.entity.vo.UseCouponsCommand;
import com.sc.nft.entity.vo.UserCouponsProductVO;
import com.sc.nft.enums.CouponsTypeEnum;
import com.sc.nft.enums.MallActivityStatusEnum;
import com.sc.nft.enums.UserCouponsStatusEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.MallActivityService;
import com.sc.nft.service.UserCouponsService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.BigDecimalUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户优惠券服务实现
 *
 * @author liGen
 * @version 1.0
 * @date 2023/12/5 4:43 下午
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserCouponsServiceImpl implements UserCouponsService {

    private final UserCouponsDao userCouponsDao;
    private final MallActivityService mallActivityService;

    /**
     * 领取优惠券
     *
     * @param activityCoupons 优惠券活动
     * @param userInfo        用户
     * @return
     */
    @Override
    public UserCoupons receive(ActivityCoupons activityCoupons, UserInfo userInfo) {
        Date now = new Date();
        UserCoupons userCoupons = new UserCoupons();
        userCoupons.setTitle(activityCoupons.getTitle());
        userCoupons.setCouponsType(activityCoupons.getCouponsType());
        userCoupons.setUserId(userInfo.getId());
        userCoupons.setUserTel(userInfo.getUserTel());
        userCoupons.setActivityCouponsId(activityCoupons.getId());
        userCoupons.setMoney(activityCoupons.getMoney());
        userCoupons.setProportion(activityCoupons.getProportion());
        userCoupons.setFullMoney(activityCoupons.getFullMoney());
        // 券有效时间开始
        DateTime effectiveTime = DateUtil.offsetDay(now, activityCoupons.getAfterDay());
        userCoupons.setEffectiveTime(effectiveTime);
        // 券有效时间结束
        DateTime expiresIn = DateUtil.offsetDay(now, activityCoupons.getValidDay());
        userCoupons.setExpiresIn(expiresIn);
        userCoupons.setProductIds(activityCoupons.getProductIds());
        userCoupons.setStatus(UserCouponsStatusEnum.UNUSED);
        userCoupons.insert();
        return userCoupons;
    }

    /**
     * 获取用户该优惠券活动下的有效优惠券
     *
     * @param userId
     * @param couponsId
     * @return
     */
    @Override
    public List<UserCoupons> getValidUserCoupons(Long userId, Long couponsId) {
        List<UserCoupons> validUserCouponsList = Lists.newArrayList();
        // 获取未使用的
        List<UserCoupons> userCouponsList = userCouponsDao.getByUserIdAndActivityCouponsId(couponsId, userId, UserCouponsStatusEnum.UNUSED);
        for (UserCoupons userCoupons : userCouponsList) {
            if (DateTime.now().before(userCoupons.getExpiresIn()) && DateTime.now().after(userCoupons.getEffectiveTime())) {
                // 获取有效期内的优惠券
                validUserCouponsList.add(userCoupons);
            }
        }
        return validUserCouponsList;
    }

    /**
     * 获取用户优惠券
     *
     * @param userId
     * @return
     */
    @Override
    public List<UserCouponsDTO> getUserCoupons(Long userId, UserCouponsStatusEnum userCouponsStatusEnum) {
        DateTime now = DateTime.now();
        List<UserCouponsDTO> userCouponsDTOList = Lists.newArrayList();
        List<UserCoupons> userCouponsList = userCouponsDao.getUserCoupons(userId);
        for (UserCoupons userCoupons : userCouponsList) {
            UserCouponsDTO userCouponsDTO = UserCouponsDTO.build(userCoupons);
            if (UserCouponsStatusEnum.UNUSED == userCoupons.getStatus()) {
                if (now.after(userCoupons.getExpiresIn())) {
                    // 已过期
                    userCouponsDTO.setStatus(UserCouponsStatusEnum.EXPIRED);
                    // 更新以减少判断
                    updateStatus(userCoupons.getId(), UserCouponsStatusEnum.EXPIRED);
                }
            }
            userCouponsDTOList.add(userCouponsDTO);
        }
        if (Objects.isNull(userCouponsStatusEnum)){
            return userCouponsDTOList;
        }else {
            List<UserCouponsDTO> userCouponsDTOS = userCouponsDTOList.stream().filter(userCouponsDTO -> userCouponsDTO.getStatus() == userCouponsStatusEnum).collect(Collectors.toList());
            return userCouponsDTOS;
        }
    }

    /**
     * 获取用户购买商品可用优惠券
     *
     * @param userId            用户ID
     * @param activityProductId 活动商品ID
     * @return
     */
    @Override
    public List<UserCouponsDTO> getUserCanCoupons(Long userId, Long activityProductId, BigDecimal orderPrice) {
        List<UserCouponsDTO> userCanCoupons = userCouponsDao.getUserCanCoupons(userId, activityProductId, orderPrice);
        return userCanCoupons;
    }

    /**
     * 修改优惠券状态 只有未使用状态可修改
     *
     * @param id
     * @param userCouponsStatusEnum
     */
    @Override
    public void updateStatus(Long id, UserCouponsStatusEnum userCouponsStatusEnum) {
        UserCoupons userCoupons = getById(id);
        if (UserCouponsStatusEnum.UNUSED == userCoupons.getStatus()) {
            userCouponsDao.updateStatus(id, userCouponsStatusEnum);
        }
    }

    /**
     * 获取用户优惠券
     *
     * @param id
     * @return
     */
    @Override
    public UserCoupons getById(Long id) {
        UserCoupons userCoupons = userCouponsDao.getById(id);
        Assert.notNull(userCoupons, () -> new GlobalRunTimeException(ErrorCode.USER_COUPONS_NOT_EXIST));
        return userCoupons;
    }

    /**
     * 获取订单下使用的优惠券
     *
     * @param orderId
     * @return
     */
    @Override
    public UserCoupons getByOrderId(Long orderId) {
        return userCouponsDao.getByOrderId(orderId);
    }

    /**
     * 使用用户优惠券
     *
     * @param userCouponsId
     * @param cmd
     * @param userId
     * @return
     */
    @Override
    public UseUserCouponsDTO useUserCoupons(Long userCouponsId, UseCouponsCommand cmd, Long userId) {
        UserCoupons userCoupons = getById(userCouponsId);
        if (Objects.isNull(userCoupons)) {
            UseUserCouponsDTO useUserCouponsDTO = new UseUserCouponsDTO();
            useUserCouponsDTO.setCanUse(false);
            useUserCouponsDTO.setCanNotUseReason("优惠券不存在");
            return useUserCouponsDTO;
        }
        UseUserCouponsDTO useUserCouponsDTO = checkUse(userCoupons, userId, cmd.getMoney(), cmd.getActivityProductId());
        if (useUserCouponsDTO.getCanUse()) {
            Date now = Calendar.getInstance().getTime();
            userCoupons.setStatus(UserCouponsStatusEnum.USED);
            userCoupons.setUseTime(now);
            userCoupons.setOrderNo(cmd.getOrderNo());
            userCoupons.setOrderId(cmd.getOrderId());
            userCoupons.updateById();
        }
        return useUserCouponsDTO;
    }

    /**
     * 优惠券能否使用校验
     *
     * @param userCoupons
     * @param userId
     * @param money
     * @param activityProductId
     * @return
     */
    @Override
    public UseUserCouponsDTO checkUse(UserCoupons userCoupons, Long userId, BigDecimal money, Long activityProductId) {
        if (Objects.isNull(userCoupons)) {
            return null;
        }
        if (UserCouponsStatusEnum.USED == userCoupons.getStatus()) {
            return UseUserCouponsDTO.build(userCoupons, false, "已使用");
        }

        if (UserCouponsStatusEnum.failList().contains(userCoupons.getStatus())) {
            return UseUserCouponsDTO.build(userCoupons, false, "已失效");
        }

        if (Objects.nonNull(money)) {
            // 优惠券满减规则
            if (BigDecimalUtils.compare(userCoupons.getFullMoney(), money)) {
                return UseUserCouponsDTO.build(userCoupons, false, "优惠券满" + userCoupons.getFullMoney() + "元可用");
            }
        } else {
            return UseUserCouponsDTO.build(userCoupons, false, "优惠券满" + userCoupons.getFullMoney() + "元可用");
        }
        // 优惠券所有人判断
        if (!userId.equals(userCoupons.getUserId())) {
            return UseUserCouponsDTO.build(userCoupons, false, "不是你的优惠券");
        }
        // 时间校验
        if (Objects.nonNull(userCoupons.getEffectiveTime()) && userCoupons.getEffectiveTime().after(new Date())) {
            return UseUserCouponsDTO.build(userCoupons, false, "优惠券未生效");
        }
        // 时间校验
        if (Objects.nonNull(userCoupons.getExpiresIn()) && userCoupons.getExpiresIn().before(new Date())) {
            return UseUserCouponsDTO.build(userCoupons, false, "优惠券已失效");
        }
        // 使用限制
        if (StringUtils.isNotBlank(userCoupons.getProductIds())) {
            List<Long> productIds = Lists.newArrayList();
            try {
                productIds = JSONArray.parseArray(userCoupons.getProductIds(), Long.class);
            } catch (Exception e) {
                log.error("解析失败: {}", userCoupons.getProductIds(), e);
                return UseUserCouponsDTO.build(userCoupons, false, "暂无可用...");
            }
            if (!productIds.contains(activityProductId)) {
                return UseUserCouponsDTO.build(userCoupons, false, "商品受限");
            }
        }
        return UseUserCouponsDTO.build(userCoupons, true, "");
    }

    /**
     * 获取用户优惠券下的可用商品
     *
     * @param userCouponsProductVO
     * @return
     */
    @Override
    public Page<ActivityCouponsProductDTO> getActivityCouponsProductDTOPage(UserCouponsProductVO userCouponsProductVO) {
        UserCoupons userCoupons = getById(userCouponsProductVO.getCouponsId());
        String productIds = userCoupons.getProductIds();
        if (org.springframework.util.StringUtils.isEmpty(productIds)) {
            return null;
        }
        List<Long> ids = JSONArray.parseArray(productIds, Long.class);
        Page<ActivityCouponsProductDTO> activityCouponsProductDTOPage = mallActivityService.getActivityCouponsProductDTOPage(ids, new Page(userCouponsProductVO.getPageNo(), userCouponsProductVO.getPageSize()),MallActivityStatusEnum.AVAILABLE.getCode());
        for (ActivityCouponsProductDTO record : activityCouponsProductDTOPage.getRecords()) {
            if(record.getSpecsCount()>1){
                record.setSalesPrice(record.getSalesPrice());
            }
            if(StrUtil.isNotBlank(record.getCoverImage())){
                record.setCoverImage(StrUtil.split(record.getCoverImage(),",").get(0));
            }
        }
        return activityCouponsProductDTOPage;
    }
}
